// bookcapDlg.cpp : implementation file
//

#include "stdafx.h"
#include "bookcap.h"
#include "bookcapDlg.h"
#include "TalkBar.h"
#include "..\caphook\caphook.h"

#include "Crop.h"
#define BOOKCAP_TOOLTIP		_T("Tally-Ho")

#define SONYA_HOMEPAGE		_T("http://code.google.com/p/tallyho")
#define SONYA_TOOLTIP		_T("Tally-Ho Screen Reader")

#define PRIV_REG_PREFIX		_T("Software\\Pimba\\TallyHo")
#define PRIV_REG_HK_CONTROL	_T("HotkeyControl")
#define PRIV_REG_HK_SHIFT	_T("HotkeyShift")
#define PRIV_REG_HK_ALT		_T("HotkeyAlt")
#define PRIV_REG_HOTKEY		_T("Hotkey")
#define PRIV_REG_APPNAME	"TallyHo"
#define PRIV_REG_COPYCLIP	_T("CopyClip")
#define PRIV_REG_SPEAK		_T("Speak")
#define PRIV_REG_WATCH		_T("WatchClip")
#define PRIV_REG_FIRST		_T("FirstRun")
#define PRIV_REG_PROCESS	_T("ProcessingLevel")
#define PRIV_REG_TALKBAR	_T("ShowBar")

#define WM_KEYSTROKE		(WM_USER + 755)
#define WM_PQUIT			(WM_USER + 756)
#define WM_PCONFIG			(WM_USER + 757)

#define EVENT_INITHIDE		(WM_USER+1)
#define EVENT_CHECKCLIP		(WM_USER+2)
#define TRAY_EVENT			(WM_USER+3)

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

NOTIFYICONDATA niData; 



CbookcapDlg::CbookcapDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CbookcapDlg::IDD, pParent), m_TessApi("eng")
{
	m_hIcon = AfxGetApp()->LoadIcon(IDI_GREEN);
	m_Crop = NULL;
    m_hMenu = ::CreatePopupMenu();
	m_result[0] = 0;
	m_underline = 0;
	m_textChange = 0;
	m_clipnum = GetClipboardSequenceNumber();
	m_BackIcon = NULL;

	HRSRC find = FindResource(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_GREEN),RT_GROUP_ICON);
	HGLOBAL load = LoadResource(NULL,find);
	PBYTE data = (PBYTE)LockResource(load);
	
	if (data) {
		int id = LookupIconIdFromDirectoryEx((PBYTE) data, TRUE,256, 256, LR_DEFAULTCOLOR);
		HRSRC find2 = FindResource(AfxGetInstanceHandle(),MAKEINTRESOURCE(id),MAKEINTRESOURCE(RT_ICON));
		HGLOBAL load2 = LoadResource(AfxGetInstanceHandle(), find2);
		PBYTE data2  = (PBYTE)LockResource(load2);
		
		if (data2) {
			int size = SizeofResource(AfxGetInstanceHandle(),find2);
			m_BackIcon = CreateIconFromResourceEx(data2,size,TRUE,0x00030000,256,256,LR_DEFAULTCOLOR);
		}
	}
	::InsertMenu(m_hMenu,0,MF_STRING|MF_BYPOSITION,WM_PCONFIG,_T("Configure..."));
	::InsertMenu(m_hMenu,1,MF_SEPARATOR|MF_BYPOSITION,0,NULL);
	::InsertMenu(m_hMenu,2,MF_STRING|MF_BYPOSITION,WM_PQUIT,_T("Quit"));
}

CbookcapDlg::~CbookcapDlg()
{
	Shell_NotifyIcon(NIM_DELETE,&niData);

}

void CbookcapDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_HK_SHIFT, m_KeyShift);
	DDX_Control(pDX, IDC_HK_CONTROL, m_KeyControl);
	DDX_Control(pDX, IDC_HK_ALT, m_KeyAlt);
	DDX_Control(pDX, IDC_HOTKEY, m_Hotkey);
	DDX_Control(pDX, IDC_AUTOSTART, m_AutoStart);
	DDX_Control(pDX, IDC_APPEND, m_AppendFile);
	DDX_Control(pDX, IDC_COPYCLIP, m_CopyClip);
	DDX_Control(pDX, IDC_SPEAK, m_Speak);
	DDX_Control(pDX, IDC_WATCHCLIP, m_WatchClip);
	DDX_Control(pDX, IDC_LINK, m_Link);
}

BEGIN_MESSAGE_MAP(CbookcapDlg, CDialog)
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_KEYSTROKE, hook_notify)
	ON_MESSAGE(TRAY_EVENT,tray_notify)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_HK_SHIFT, &CbookcapDlg::OnBnClickedHotKey)
	ON_BN_CLICKED(IDC_HK_ALT, &CbookcapDlg::OnBnClickedHotKey)
	ON_BN_CLICKED(IDC_HK_CONTROL, &CbookcapDlg::OnBnClickedHotKey)
	ON_EN_CHANGE(IDC_HOTKEY, &CbookcapDlg::OnBnClickedHotKey)
	ON_BN_CLICKED(IDC_AUTOSTART, &CbookcapDlg::OnBnClickedAutostart)
	ON_BN_CLICKED(IDC_APPEND, &CbookcapDlg::OnBnClickedAppend)
	ON_BN_CLICKED(IDC_COPYCLIP, &CbookcapDlg::OnBnClickedCopyclip)
	ON_BN_CLICKED(IDC_SPEAK, &CbookcapDlg::OnBnClickedSpeak)
	ON_BN_CLICKED(IDC_WATCHCLIP, &CbookcapDlg::OnBnClickedWatchclip)
	ON_WM_PAINT()
	ON_WM_CTLCOLOR()
	ON_WM_SETCURSOR()
	ON_WM_LBUTTONDBLCLK()
END_MESSAGE_MAP()


// CbookcapDlg message handlers

BOOL CbookcapDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

    initHotkey();
    initAutostart();	
	initClipSpeak();
	initAppendFile();
	m_cpVoice.CoCreateInstance( CLSID_SpVoice );

	m_LinkCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_HAND));

	EnableToolTips();
	m_Tooltip.Create( this );
	m_Tooltip.AddTool( &m_Link, SONYA_TOOLTIP );

	LOGFONT lf;
	HFONT hOrigFont = (HFONT) ::SendMessage(m_Link.m_hWnd, WM_GETFONT, 0, 0);
	GetObject(hOrigFont, sizeof(lf), &lf);
	lf.lfUnderline = TRUE;
	m_hFont = CreateFontIndirect(&lf);

	SetIcon(m_hIcon, TRUE);
	SetIcon(m_hIcon, FALSE);

	installhook(GetSafeHwnd());
	create_tray();

	SetTimer(EVENT_INITHIDE,1,NULL);
	SetTimer(EVENT_CHECKCLIP,100,NULL);

	firstRun();

    m_TalkBar = new CTalkBar(this);
    m_TalkBar->Create(IDD_TOOLBAR);
	m_TalkBar->ShowWindow(GetTalkBar() ? SW_SHOW : SW_HIDE);

	return TRUE;  // return TRUE  unless you set the focus to a control
}


// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CbookcapDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

LRESULT CbookcapDlg::hook_notify(WPARAM w, LPARAM l)//definition
{
	if (w == 27)
		cancelCrop();

	if ((w != 27) && (m_Crop == NULL)) {
		startCrop();
		return 1L;
	}

	return 0L;
}

void CbookcapDlg::stopVoice()
{
	m_cpVoice->Speak( NULL, SPF_PURGEBEFORESPEAK, 0 );
}

void CbookcapDlg::startCrop()
{
	stopVoice();

	m_Crop = new CCrop(this);
	m_Crop->start();
}

void CbookcapDlg::cancelCrop()
{
	stopVoice();

	if (m_Crop) 
		m_Crop->cancel();
}

void CbookcapDlg::create_tray()
{
	ZeroMemory(&niData,sizeof(NOTIFYICONDATA));
    niData.cbSize = sizeof(NOTIFYICONDATA);
	wcscpy(niData.szTip,BOOKCAP_TOOLTIP);

    niData.uID = IDI_GREEN;
    niData.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP;
    niData.hIcon =
        (HICON)LoadImage( AfxGetInstanceHandle(),
            MAKEINTRESOURCE(IDI_GREEN),
            IMAGE_ICON,
            GetSystemMetrics(SM_CXSMICON),
            GetSystemMetrics(SM_CYSMICON),
            LR_DEFAULTCOLOR);

	niData.hWnd = GetSafeHwnd();
    niData.uCallbackMessage = TRAY_EVENT;
	Shell_NotifyIcon(NIM_ADD,&niData);

}


LRESULT CbookcapDlg::tray_notify(WPARAM w, LPARAM l)//definition
{
	if ((l == WM_RBUTTONDOWN) || (l == WM_CONTEXTMENU)) {

		POINT pt;
		GetCursorPos(&pt);

		SetForegroundWindow();
		TrackPopupMenu(m_hMenu,0,pt.x,pt.y,0,GetSafeHwnd(),NULL);
		return 1L;
	}

	if (l == WM_LBUTTONDBLCLK) {
		ShowTalkBar(1);
		return 1L;
	}

	return 0L;
}


void CbookcapDlg::OnTimer(UINT_PTR nIDEvent)
{
	if (nIDEvent == EVENT_INITHIDE) {
		ShowWindow(SW_HIDE);
		KillTimer(EVENT_INITHIDE);
		return;
	}

	if (nIDEvent == EVENT_CHECKCLIP) {
		checkClipboard();
		return;
	}	

	CDialog::OnTimer(nIDEvent);
}

int CbookcapDlg::GetTalkBar()
{
	HKEY MyKey = NULL;
	int show = 1;
	DWORD size = sizeof(DWORD);

	::RegOpenKeyEx(HKEY_CURRENT_USER,PRIV_REG_PREFIX, 0, KEY_READ|KEY_WRITE, &MyKey);
	if (MyKey) {
		::RegQueryValueEx(MyKey,PRIV_REG_TALKBAR,NULL,NULL,(LPBYTE)&show,&size);
		::RegCloseKey (MyKey);
	}

	return show;
}

void CbookcapDlg::ShowTalkBar(int show)
{
	HKEY MyKey = NULL;
	::RegCreateKeyEx(HKEY_CURRENT_USER,PRIV_REG_PREFIX, 0,NULL, 0,KEY_ALL_ACCESS, NULL,&MyKey,NULL);
	if (MyKey) {
		::RegSetValueEx(MyKey,PRIV_REG_TALKBAR,0,REG_DWORD,(BYTE*)&show,4);
		::RegCloseKey (MyKey);
	}	

	m_TalkBar->ShowWindow(show ? SW_SHOW : SW_HIDE);
}

void CbookcapDlg::OnBnClickedHotKey()
{
	if (m_textChange)
		return;

	CString text;
	DWORD control = (m_KeyControl.GetCheck() == BST_CHECKED);
	DWORD shift = (m_KeyShift.GetCheck() == BST_CHECKED);
	DWORD alt = (m_KeyAlt.GetCheck() == BST_CHECKED);
	DWORD key = 'A';

	m_Hotkey.GetWindowTextW(text);
	text.MakeUpper();
	if (text.GetLength() >= 1) 
		key = text.GetAt(text.GetLength() - 1);

	text.Empty();
	text.Insert(0,(unsigned char)key);
	m_textChange = 1;
	m_Hotkey.SetWindowTextW(text);
	m_Hotkey.SetSel(HIWORD(0), -1);
	m_textChange = 0;

	HKEY MyKey = NULL;
	::RegCreateKeyEx(HKEY_CURRENT_USER,PRIV_REG_PREFIX, 0,NULL, 0,KEY_ALL_ACCESS, NULL,&MyKey,NULL);
	if (MyKey) {
		::RegSetValueEx(MyKey,PRIV_REG_HK_CONTROL,0,REG_DWORD,(BYTE*)&control,4);
		::RegSetValueEx(MyKey,PRIV_REG_HK_SHIFT,0,REG_DWORD,(BYTE*)&shift,4);
		::RegSetValueEx(MyKey,PRIV_REG_HK_ALT,0,REG_DWORD,(BYTE*)&alt,4);
		::RegSetValueEx(MyKey,PRIV_REG_HOTKEY,0,REG_DWORD,(BYTE*)&key,4);
		::RegCloseKey (MyKey);
	}	

	define_capkey((unsigned char)key, (unsigned char)alt, (unsigned char)control, (unsigned char)shift);
}

void CbookcapDlg::firstRun()
{
	HKEY MyKey = NULL;
	int first = 0;
	int second = 1;
	DWORD size = sizeof(DWORD);

	::RegOpenKeyEx(HKEY_CURRENT_USER,PRIV_REG_PREFIX, 0, KEY_READ|KEY_WRITE, &MyKey);
	if (MyKey) {
		::RegQueryValueEx(MyKey,PRIV_REG_FIRST,NULL,NULL,(LPBYTE)&first,&size);
		::RegSetValueEx(MyKey,PRIV_REG_FIRST,0,REG_DWORD,(BYTE*)&second,4);
		::RegCloseKey (MyKey);
	}

	if (first)
		return;

	NOTIFYICONDATA IconData;
	memset(&IconData,0,sizeof(NOTIFYICONDATA));

	IconData.cbSize = sizeof(NOTIFYICONDATA);
	IconData.hWnd = GetSafeHwnd();
	IconData.uID = IDI_GREEN;
	IconData.uFlags = NIF_INFO;
	IconData.dwInfoFlags = NIIF_INFO;
	IconData.uTimeout = 10000;

	wcscpy(IconData.szInfoTitle, BOOKCAP_TOOLTIP);
	wcscpy(IconData.szInfo, _T("Right Click --> Configure to Set Options...                       "));

	Shell_NotifyIcon(NIM_MODIFY, &IconData);
}

int CbookcapDlg::getProcessingLevel()
{
	HKEY MyKey = NULL;
	int process = 180;
	DWORD size = sizeof(DWORD);	

	::RegOpenKeyEx(HKEY_CURRENT_USER,PRIV_REG_PREFIX, 0, KEY_READ, &MyKey);
	if (MyKey) {
		::RegQueryValueEx(MyKey,PRIV_REG_PROCESS,NULL,NULL,(LPBYTE)&process,&size);
		::RegCloseKey (MyKey);
	}

	if ((process < 0) || (process > 255))
		process = 180;

	return process;
}

void CbookcapDlg::initHotkey()
{
	HKEY MyKey = NULL;
	CString text;
	DWORD size = sizeof(DWORD);
	DWORD control = 0;
	DWORD shift = 1;
	DWORD alt = 1;
	DWORD key = 'A';
	
	::RegOpenKeyEx(HKEY_CURRENT_USER,PRIV_REG_PREFIX, 0, KEY_READ, &MyKey);
	if (MyKey) {
		::RegQueryValueEx(MyKey,PRIV_REG_HK_CONTROL,NULL,NULL,(LPBYTE)&control,&size);
		::RegQueryValueEx(MyKey,PRIV_REG_HK_SHIFT,NULL,NULL,(LPBYTE)&shift,&size);
		::RegQueryValueEx(MyKey,PRIV_REG_HK_ALT,NULL,NULL,(LPBYTE)&alt,&size);
		::RegQueryValueEx(MyKey,PRIV_REG_HOTKEY,NULL,NULL,(LPBYTE)&key,&size);
		::RegCloseKey (MyKey);
	}

	m_KeyControl.SetCheck(control ? BST_CHECKED : BST_UNCHECKED);
	m_KeyShift.SetCheck(shift ? BST_CHECKED : BST_UNCHECKED);
	m_KeyAlt.SetCheck(alt ? BST_CHECKED : BST_UNCHECKED);
	
	text.Empty();
	text.Insert(0,(unsigned char)key);
	m_Hotkey.SetWindowTextW(text);

	define_capkey((unsigned char)key, (unsigned char)alt, (unsigned char)control, (unsigned char)shift);
}


void CbookcapDlg::initAutostart()
{
	char buf[512];
	buf[0] = 0;
	HKEY MyKey = NULL;
	DWORD lSize = sizeof(buf)-1;

	::RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), 0, KEY_READ, &MyKey);
	if (MyKey) {
		::RegQueryValueExA(MyKey,PRIV_REG_APPNAME,NULL,NULL,(LPBYTE)buf,&lSize);
		::RegCloseKey (MyKey);
	}

	m_AutoStart.SetCheck(strlen(buf) > 0 ? BST_CHECKED : BST_UNCHECKED);
}

void CbookcapDlg::OnBnClickedAutostart()
{
	HKEY MyKey = NULL;
	char buffer[512];
	strcpy(buffer,GetCommandLineA());

	if (strstr(buffer,"-boot") == NULL)
		strcat(buffer," -boot");

	::RegCreateKeyExA(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0,NULL, 0,KEY_ALL_ACCESS, NULL,&MyKey,NULL);
	if (MyKey) {
		if (m_AutoStart.GetCheck() != BST_CHECKED)
			::RegDeleteValueA(MyKey,PRIV_REG_APPNAME);
		else
			::RegSetValueExA(MyKey,PRIV_REG_APPNAME,0,REG_SZ,(BYTE*)buffer,(DWORD)strlen(buffer)+1);

		::RegCloseKey (MyKey);
	}
}

void CbookcapDlg::initAppendFile()
{
	m_Filename[0] = 0;
}

void CbookcapDlg::OnBnClickedAppend()
{
	HKEY MyKey = NULL;
	DWORD append = (m_AppendFile.GetCheck() == BST_CHECKED);

	if (append) {
		OPENFILENAME filename;
		memset(&filename,0,sizeof(filename));

		filename.lStructSize = sizeof(filename);
		filename.lpstrFilter = _T("Text Files\0*.txt\0\0");
		filename.lpstrFile = m_Filename;
		filename.nMaxFile = 500;
		filename.lpstrTitle = _T("Append Recognized Text To...");

		if (!GetSaveFileName(&filename)) 
			append = 0;
	}

	m_AppendFile.SetCheck(append ? BST_CHECKED : BST_UNCHECKED);
}

void CbookcapDlg::appendFile()
{
	if (m_AppendFile.GetCheck() != BST_CHECKED)
		return;

	FILE *f = _wfopen(m_Filename,_T("a+"));
	if (f != NULL) {
		fwrite("\r\n",1,2,f);
		fwrite(m_result,1,strlen(m_result),f);
		fwrite("\r\n",1,2,f);
		fclose(f);
	}
}

void CbookcapDlg::OnBnClickedCopyclip()
{
	HKEY MyKey = NULL;
	DWORD clip = (m_CopyClip.GetCheck() == BST_CHECKED);

	::RegCreateKeyEx(HKEY_CURRENT_USER,PRIV_REG_PREFIX, 0,NULL, 0,KEY_ALL_ACCESS, NULL,&MyKey,NULL);
	if (MyKey) {
		::RegSetValueEx(MyKey,PRIV_REG_COPYCLIP,0,REG_DWORD,(BYTE*)&clip,4);
		::RegCloseKey (MyKey);
	}	
}

void CbookcapDlg::OnBnClickedSpeak()
{
	HKEY MyKey = NULL;
	DWORD speak = (m_Speak.GetCheck() == BST_CHECKED);

	::RegCreateKeyEx(HKEY_CURRENT_USER,PRIV_REG_PREFIX, 0,NULL, 0,KEY_ALL_ACCESS, NULL,&MyKey,NULL);
	if (MyKey) {
		::RegSetValueEx(MyKey,PRIV_REG_SPEAK,0,REG_DWORD,(BYTE*)&speak,4);
		::RegCloseKey (MyKey);
	}	

	m_WatchClip.EnableWindow(speak);
}

void CbookcapDlg::OnBnClickedWatchclip()
{
	HKEY MyKey = NULL;
	DWORD watch = (m_WatchClip.GetCheck() == BST_CHECKED);

	::RegCreateKeyEx(HKEY_CURRENT_USER,PRIV_REG_PREFIX, 0,NULL, 0,KEY_ALL_ACCESS, NULL,&MyKey,NULL);
	if (MyKey) {
		::RegSetValueEx(MyKey,PRIV_REG_WATCH,0,REG_DWORD,(BYTE*)&watch,4);
		::RegCloseKey (MyKey);
	}	

	if (watch)
		initCopyClip();
}

void CbookcapDlg::initClipSpeak()
{
	HKEY MyKey = NULL;
	DWORD clip = 1;
	DWORD speak = 1;
	DWORD watch = 1;
	DWORD size = sizeof(DWORD);

	::RegOpenKeyEx(HKEY_CURRENT_USER,PRIV_REG_PREFIX, 0, KEY_READ, &MyKey);
	if (MyKey) {
		::RegQueryValueEx(MyKey,PRIV_REG_COPYCLIP,NULL,NULL,(LPBYTE)&clip,&size);
		::RegQueryValueEx(MyKey,PRIV_REG_SPEAK,NULL,NULL,(LPBYTE)&speak,&size);
		::RegQueryValueEx(MyKey,PRIV_REG_WATCH,NULL,NULL,(LPBYTE)&watch,&size);
		::RegCloseKey (MyKey);
	}

	m_CopyClip.SetCheck(clip ? BST_CHECKED : BST_UNCHECKED);
	m_Speak.SetCheck(speak ? BST_CHECKED : BST_UNCHECKED);
	m_WatchClip.SetCheck(watch ? BST_CHECKED : BST_UNCHECKED);

	m_WatchClip.EnableWindow(speak);

	if (watch)
		initCopyClip();
}

BOOL CbookcapDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
	int selection = LOWORD(wParam);

	if (selection == IDC_LINK) {
		ShellExecute(m_hWnd, _T("open"),SONYA_HOMEPAGE, NULL, NULL, SW_SHOWNORMAL);
		return true;
	}

	if (selection == WM_PCONFIG) {
		ShowWindow(SW_SHOW);
		return true;
	}

	if (selection == WM_PQUIT) {
		EndDialog(0);
		return true;
	}

	return CDialog::OnCommand(wParam, lParam);
}

void CbookcapDlg::cropCompleted(int status)
{
	if (m_Crop == NULL)
		return;

	if (status) {
		processCrop();
		copyClipboard();
		appendFile();
		speakSelection();
	}

	delete m_Crop;
	m_Crop = NULL;
}

void CbookcapDlg::processCrop()
{
	int i,j;
	int x = m_Crop->getSizeX();
	int y = m_Crop->getSizeY();
	int cutoff = getProcessingLevel();
	unsigned char *bitmap = (unsigned char*)malloc(x*y);
	
	// preprocess page
	for (i = 0; i < x; i++)
		for (j = 0; j < y; j++) {
			COLORREF clr = m_Crop->getPixel(i,j);
			int val = (GetRValue(clr)+GetGValue(clr)+GetBValue(clr))/3;
			bitmap[i+(j*x)] = (cutoff > 0) ? (val > cutoff ? 255 : 0) : val;
		}
	
	// do ocr
	m_TessApi.BeginPageUpright(x, y, bitmap,8);
	ETEXT_DESC* output = m_TessApi.Recognize_all_Words();
	free(bitmap);
	m_TessApi.EndPage();

	// convert to text
	// minimal utf8 conversion (copy ascii, ignore the rest), insert spaces and fix hyphenation 
	j = 0;
	int last_left = 0;
	char last_char = 0;
	for (i = 0; (i < output->count) && (j < MAX_OCR_RESULT); i++) {
		if ((output->text[i].char_code & 0x80) == 0) {		// quick hack utf8 --> ascii
			if (last_left > output->text[i].left) {
				if (last_char == '-')
					j--;
				else
					m_result[j++] = ' ';
			}
			last_left = output->text[i].left;
			for (int l = 0; l < output->text[i].blanks; l++) 
				m_result[j++] = ' ';
			m_result[j++] = (char)(output->text[i].char_code);
			last_char = (char)(output->text[i].char_code);
		}
	}
	m_result[j] = 0;
}

void CbookcapDlg::copyClipboard()
{
	if (m_CopyClip.GetCheck() != BST_CHECKED)
		return;

	if(OpenClipboard()) {
		HGLOBAL clipbuffer;
		char *buffer;
		EmptyClipboard();
		clipbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(m_result)+1);
		buffer = (char*)GlobalLock(clipbuffer);
		strcpy(buffer, (char*)m_result);
		GlobalUnlock(clipbuffer);
		SetClipboardData(CF_TEXT,clipbuffer);
		CloseClipboard();
	}
	
	m_clipnum = GetClipboardSequenceNumber();
}

void CbookcapDlg::speakSelection()
{
	if (m_Speak.GetCheck() != BST_CHECKED)
		return;

//	stopVoice();

	if (isSpeaking())
		return;

	MultiByteToWideChar(CP_ACP, 0, (LPCSTR)m_result, -1, m_wresult, MAX_OCR_RESULT);
	m_cpVoice->Speak( m_wresult, SPF_ASYNC | SPF_IS_NOT_XML, 0 );
}

int CbookcapDlg::isSpeaking()
{
	SPVOICESTATUS status;

	m_cpVoice->GetStatus(&status,NULL);

	return (status.dwRunningState == SPRS_IS_SPEAKING);
}


void CbookcapDlg::initCopyClip()
{
	m_clipnum = GetClipboardSequenceNumber();
}

void CbookcapDlg::checkClipboard()
{
	char * buffer;
	int speak = 0;

	if (m_WatchClip.GetCheck() != BST_CHECKED)
		return;

	if (m_clipnum != GetClipboardSequenceNumber()) {
		m_clipnum = GetClipboardSequenceNumber();
		
		if(OpenClipboard()) {
			buffer = (char*)GetClipboardData(CF_TEXT);
			if (buffer != NULL) {
				strncpy(m_result,buffer,MAX_OCR_RESULT);
				m_result[MAX_OCR_RESULT] = 0;
				speak = 1;
			}
			CloseClipboard();
		}	

	}

	if (speak)
		speakSelection();
}


void CbookcapDlg::OnCancel()
{
	ShowWindow(SW_HIDE);
}

void CbookcapDlg::OnPaint()
{
	CRect rect;
	CPaintDC dc(this); // device context for painting

	GetWindowRect(rect);

	DrawIconEx(dc.m_hDC,rect.Width()-256+40,10,(HICON)m_BackIcon,256,256,0,NULL,DI_NORMAL);

}

HBRUSH CbookcapDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

	if (pWnd->m_hWnd == m_Link.m_hWnd)  {
		SetTextColor(pDC->m_hDC, RGB(0, 0, 255));

		if (m_underline) 
			SelectObject(pDC->m_hDC,m_hFont);

	}

	return hbr;
}

BOOL CbookcapDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
	if ((pWnd->m_hWnd == m_Link.m_hWnd)) {
		m_underline = 1;
		m_Link.Invalidate();
		SetCursor(m_LinkCursor);
		return true;
	}
	
	if (m_underline) {
		m_underline = 0;
		m_Link.Invalidate();
	}
	return CDialog::OnSetCursor(pWnd, nHitTest, message);
}

BOOL CbookcapDlg::PreTranslateMessage(MSG* pMsg)
{
	 m_Tooltip.RelayEvent( pMsg );

	return CDialog::PreTranslateMessage(pMsg);
}

void CbookcapDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	NOTIFYICONDATA IconData;
	memset(&IconData,0,sizeof(NOTIFYICONDATA));

	IconData.cbSize = sizeof(NOTIFYICONDATA);
	IconData.hWnd = GetSafeHwnd();
	IconData.uID = IDI_GREEN;
	IconData.uFlags = NIF_INFO|NIF_ICON;
	IconData.dwInfoFlags = NIIF_USER;
	IconData.hIcon = m_hIcon;
	IconData.uTimeout = 30000;

	wcscpy(IconData.szInfoTitle, BOOKCAP_TOOLTIP);
	wcscpy(IconData.szInfo, _T("\nWriten by Aviv Bergman, 2008\n\nUses Icons from http://fasticon.com (thanks!)\nand the Tesseract OCR library (Thanks Google!)  "));

	Shell_NotifyIcon(NIM_MODIFY, &IconData);	

	CDialog::OnLButtonDblClk(nFlags, point);
}
